package cn.biao.epic.sys.modular.system.service;

import cn.biao.epic.base.pojo.page.AntdPageFactory;
import cn.biao.epic.core.util.ToolUtil;
import cn.biao.epic.model.exception.RequestEmptyException;
import cn.biao.epic.model.exception.ServiceException;
import cn.biao.epic.sys.core.constant.factory.ConstantFactory;
import cn.biao.epic.sys.core.constant.state.MenuStatus;
import cn.biao.epic.sys.core.exception.enums.BizExceptionEnum;
import cn.biao.epic.sys.modular.system.entity.Menu;
import cn.biao.epic.sys.modular.system.mapper.MenuMapper;
import cn.biao.epic.sys.modular.system.model.MenuDto;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Auther Uncle_Z
 * @date 2019/12/6 18:09
 * @Email:2545375@qq.com
 * @Descrition
 */
@Service
public class MenuService extends ServiceImpl<MenuMapper, Menu> {

    /**
     *
     * 添加菜单
     *
     * @author uncle_z
     * @Date 2019/12/10 16:22
     * @Param [menuDto]
     * @File MenuService.java
     */
    @Transactional
    @ResponseBody
    public void addMenu(MenuDto menuDto){
        if (ToolUtil.isOneEmpty(menuDto,menuDto.getCode(),menuDto.getName(),menuDto.getPid(),menuDto.getMenuFlag(),
                menuDto.getUrl(),menuDto.getSystemType())) {
            throw new RequestEmptyException();
        }

        //判断是否已经存在该编号
        String existsMenuName = ConstantFactory.me().getMenuNameByCode(menuDto.getCode());
        if (ToolUtil.isNotEmpty(existsMenuName)) {
            throw new ServiceException(BizExceptionEnum.EXISTED_THE_MENU);
        }
        Menu resultMenu = this.menuSetPcode(menuDto);
        resultMenu.setStatus(MenuStatus.ENABLE.getCode());
        this.save(resultMenu);
    }


    /**
     *
     * 更新
     *
     * @author uncle_z
     * @Date 2019/12/10 16:22
     * @Param [menuDto]
     * @File MenuService.java
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateMenu(MenuDto menuDto){
        if (menuDto == null || ToolUtil.isOneEmpty(menuDto.getMenuId(),menuDto.getCode())) {
            throw new RequestEmptyException();
        }
        Long id = menuDto.getMenuId();
        Menu menu = getById(id);
        if (menu == null) {
            throw new RequestEmptyException();
        }
        Menu resultMenu = this.menuSetPcode(menuDto);

        updateSubMenuLevels(menu, resultMenu);
        updateById(resultMenu);
    }

    /**
     *
     * 更新所有子菜单的结构
     *
     * @author uncle_z
     * @Date 2019/12/10 16:23
     * @Param [oldMenu, newMenu]
     * @File MenuService.java
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSubMenuLevels(Menu oldMenu, Menu newMenu) {
        List<Menu> menus = baseMapper.selectMenulikePcodes(oldMenu.getCode());
        menus.forEach(v -> {
            if (oldMenu.getCode().equals(v.getCode())) {
                v.setPcode(newMenu.getCode());
            }
            //更新pcodes
            String oldPcodesPrefix = oldMenu.getPcodes() + "[" + oldMenu.getCode() + "],";
            String oldPcodesSuffix = v.getPcodes().substring(oldPcodesPrefix.length());
            String menuPcodes = newMenu.getPcodes() + "[" +newMenu.getCode()+ "]," + oldPcodesSuffix;
            v.setPcodes(menuPcodes);
            int level = StrUtil.count(menuPcodes,"[");
            v.setLevels(level);
            v.setSystemType(newMenu.getSystemType());
            updateById(v);
        });
    }

    /**
     * 
     * 删除菜单包
     *
     * @author uncle_z
     * @Date 2019/12/10 16:24
     * @Param [menuId]
     * @File MenuService.java 
     */
    @Transactional
    public void deleteMenu(Long menuId) {
        baseMapper.deleteById(menuId);

        baseMapper.deleteRelationByMenu(menuId);
    }


    /**
     * 
     * 删除菜单包含所有子菜单
     *
     * @author uncle_z
     * @Date 2019/12/10 16:27
     * @Param [menuId]
     * @File MenuService.java 
     */
    @Transactional
    public void delMenuContainSubMenus(Long menuId) {
        Menu menu = baseMapper.selectById(menuId);

        deleteMenu(menuId);
        List<Menu> menus = baseMapper.selectMenulikePcodes(menu.getCode());
        menus.forEach(v -> deleteMenu(v.getMenuId()));
    }


    /**
     * 
     * 根据条件查询菜单
     *
     * @author uncle_z
     * @Date 2019/12/10 17:09
     * @Param [condition, level, menuId]
     * @File MenuService.java 
     */
    public Page<Map<String, Object>> selectMenus(String condition, String level, Long menuId) {
        String code = "";
        if (menuId != null && menuId != 0L) {
            Menu menu = getById(menuId);
            code = menu.getCode();
        }
        Page page = AntdPageFactory.defaultPage();
        return baseMapper.selectMenus(page, condition, level, menuId, code);
    }

    /**
     * 
     * 根据条件查询菜单
     *
     * @author uncle_z
     * @Date 2019/12/10 17:11
     * @Param [roleId]
     * @File MenuService.java 
     */
    public List<Long> getMenuIdsByRoleId(Long roleId) {
        return baseMapper.getMenuIdsByRoleId(roleId);
    }

    /**
     * 
     * 删除menu关联的relation
     *
     * @author uncle_z
     * @Date 2019/12/10 17:12
     * @Param [menuId]
     * @File MenuService.java 
     */
    public int deleteRelationByMenu(Long menuId) {
        return baseMapper.deleteRelationByMenu(menuId);
    }

    /**
     * 获取资源url通过角色id
     *
     * @param roleId
     * @return
     * @date 2017年2月19日 下午7:12:38
     */
    public List<String> getResUrlsByRoleId(Long roleId) {
        return baseMapper.selectUrlsByRoleId(roleId);
    }

    /**
     * 根据code查询菜单
     *
     */
    public Menu selectByCode(String code) {
        Menu menu = new Menu();
        menu.setCode(code);
        QueryWrapper<Menu> queryWrapper = new QueryWrapper<>(menu);
        return this.baseMapper.selectOne(queryWrapper);
    }


    public Menu menuSetPcode(MenuDto menuParam) {

        Menu resultMenu = new Menu();
        BeanUtil.copyProperties(menuParam, resultMenu);

        if (ToolUtil.isEmpty(menuParam.getPid()) || menuParam.getPid().equals(0L)) {
            resultMenu.setPcode("0");
            resultMenu.setPcodes("[0],");
            resultMenu.setLevels(1);
        } else {
            Long pid = menuParam.getPid();
            Menu pMenu = this.getById(pid);
            Integer pLevels = pMenu.getLevels();
            resultMenu.setPcode(pMenu.getCode());

            //如果编号和父编号一致会导致无限递归
            if (menuParam.getCode().equals(menuParam.getPcode())) {
                throw new ServiceException(BizExceptionEnum.MENU_PCODE_COINCIDENCE);
            }

            resultMenu.setLevels(pLevels + 1);
            resultMenu.setPcodes(pMenu.getPcodes() + "[" + pMenu.getCode() + "],");
        }

        return resultMenu;
    }

    /**
     * 获取菜单树形列表
     *
     */
    public List<Map<String, Object>> selectMenuTree(String condition, String level) {
        List<Map<String, Object>> maps = this.baseMapper.selectMenuTree(condition, level);

        if (maps == null) {
            maps = new ArrayList<>();
        }

        //修复菜单查询bug，带条件的暂时先父级置为0
        if (ToolUtil.isNotEmpty(condition) || ToolUtil.isNotEmpty(level)) {
            if (maps.size() > 0) {

                //将pcode置为root
                for (Map<String, Object> menu : maps) {
                    menu.put("pcode", "0");
                }
            }
        }

        //创建根节点
        Menu menu = new Menu();
        menu.setMenuId(-1L);
        menu.setName("根节点");
        menu.setCode("0");
        menu.setPcode("-2");
        maps.add(BeanUtil.beanToMap(menu));

        return maps;
    }
}
